package com.jeesite.modules.dataScreen.ssm;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class SmsSendService {
    @Resource
    private RestTemplate restTemplate;
    private HttpHeaders headers;

    @Value("${sms.sendSmsUrl}")
    private String sendSmsUrl;
    @Value("${sms.reportUrl}")
    private String reportUrl;
    @Value("${sms.spCode}")
    private String spCode;
    @Value("${sms.loginName}")
    private String loginName;
    @Value("${sms.password}")
    private String password;

    @PostConstruct
    public void init() {
        StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("GBK"));
        restTemplate.getMessageConverters().add(0, converter);

        headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    }

    /**
     * 发送短信，使用默认模板
     *
     * @param messageContent 短信内容
     * @param userNumbers    发送目标的手机号，可传多个
     * @return Map<String, String>,result=0成功，serialNumber流水号
     */
    public Map<String, String> send(String messageContent, String... userNumbers) {
        return this.send(messageContent, null, null, userNumbers);
    }

    /**
     * 发送短信，使用指定模板
     *
     * @param messageContent 短信内容
     * @param templateId     模板id
     * @param scheduleTime   预约发送时间，为空或小于当前时间5分钟立即发送
     * @param userNumbers    发送目标手机号码数组
     * @return Map<String, String>,result=0成功，serialNumber流水号
     */
    public Map<String, String> send(String messageContent, String templateId, String scheduleTime, String[] userNumbers) {
        if (userNumbers.length == 0) {
            Map<String, String> map = new HashMap<>();
            map.put("result", "手机号码个数不能为0");
            return map;
        }
        //生成请求体数据
        SmsSendParams params = new SmsSendParams()
                .setLoginName(loginName)
                .setPassword(password)
                .setSpCode(spCode)
                .setTemplateId(templateId)
                .setUserNumber(userNumbers)
                .setMessageContent(messageContent)
                .setScheduleTime(scheduleTime)
                .setF("1");
        //流水号，一个随机数,生成规则 当前时间戳+一个7位随机数，凑够20个数
        long now = new Date().getTime();
        String random = RandomUtil.randomNumbers(7);
        String serialNumber = now + random;
        params.setSerialNumber(serialNumber);
        log.info("短信发送 参数 params：{}", JSON.toJSONString(params));
        //发送
        ResponseEntity<String> responseEntity = restTemplate.exchange(
                sendSmsUrl,
                HttpMethod.POST,
                new HttpEntity<>(params.toString(), headers),
                String.class
        );

        String body = responseEntity.getBody();
        Map<String, String> map = strToMap(body);
        map.put("serialNumber", serialNumber);
        log.info("短信发送 结果 map：{}", JSON.toJSONString(map));
        return map;
    }

    /**
     * 获取短信回执信息
     *
     * @return
     */
    public Map<String, String> report(String serialNumber) {
        SmsSendParams params = new SmsSendParams()
                .setSpCode(spCode)
                .setLoginName(loginName)
                .setPassword(password);

        //发送
        ResponseEntity<String> responseEntity = restTemplate.exchange(
                reportUrl,
                HttpMethod.POST,
                new HttpEntity<>(params.toString(), headers),
                String.class
        );

        String body = responseEntity.getBody();
        Map<String, String> map = strToMap(body);
        String out = map.get("out");
        String result = map.get("result");
        Map<String, String> m = new HashMap<>();
        if (out != null) {
            Arrays.stream(out.split(";")).filter(i -> i.contains(serialNumber))
                    .forEach(i -> {
                        String[] info = i.split(",");
                        m.put("serialNumber", info[0]);
                        m.put("tel", info[1]);
                        m.put("result", info[2]);
                    });
        }
        return m;
    }

    //将 k1=v1&k2=v2格式的字符串解析成map
    private Map<String, String> strToMap(String bodyStr) {
        Map<String, String> map = new HashMap<>();

        String[] kv = bodyStr.split("&");
        Arrays.stream(kv).forEach(i -> {
            String[] data = i.split("=");
            if (data.length > 1) {
                map.put(data[0], data[1]);
            } else {
                map.put(data[0], null);
            }
        });

        return map;
    }

}
